//
//  SipManager.m
//  Sip
//
//  Created by Erphan on 12/21/10.
//  Copyright 2010 Smonte. All rights reserved.
//

#import "SipManager.h"
#import "SipAccountInfo.h"
#import "Constants.h"
#import <AVFoundation/AVFoundation.h>

@interface SipManager ()
- (void) on_registration_state:(NSNotification *)note;
- (void) on_call_state:(NSNotification *)note;
- (void)initSilence;
- (void)playSilence;
- (void)stopSilence;
- (Float32)audioVolume;
@end

@implementation SipManager

void audioRouteChangeListenerCallback (void *inUserData, AudioSessionPropertyID inPropertyID, UInt32 inPropertyValueSize, const void *inPropertyValue)
{
    //if (inPropertyID != kAudioSessionProperty_AudioRouteChange) return;
    
    NSLog(@"PROPERTY: %lu", inPropertyID);
}

- (id)init {
    self = [super init];
	if (self) {
		[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(on_call_state:) name:SIP_CALLSTATE object:nil];
		[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(on_registration_state:) name:SIP_REGCALLBACK object:nil];

//        AudioSessionInitialize(NULL, NULL, NULL, NULL);
//        AudioSessionPropertyID routeChangeID = kAudioSessionProperty_CurrentHardwareOutputVolume;
//        AudioSessionAddPropertyListener (routeChangeID, audioRouteChangeListenerCallback, self);
	}
	return self;
}

- (void)connect:(NSString *)server :(NSString *)user :(NSString *)password {
	if (!sip) {
		sip = [[PjSip alloc] initWithManager:self];	
		sip.sipDomain = server;
		bSipInitialized = [sip initializePJ];
	}
	sip.sipDomain = server;
	sip.sipUserName = user;
	sip.sipPassword = password;
	if (bSipInitialized) {
		[sip connect];
        [self initSilence];
	}
	else {
		NSLog(@"Unable to connect");
		bSipInitialized = [sip initializePJ];
	}
}

- (void)disconnect {
	[sip disconnect];
}

- (BOOL)makeCall:(NSString *)number {
	if ([sip.sipUserName isEqualToString:number]) {
		UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:APP_NAME 
														message:@"Cannot call yourself" 
													   delegate:nil 
											  cancelButtonTitle:@"OK" 
											  otherButtonTitles:nil] autorelease];
		[alert show];
		return NO;
	}
	return [sip makeCall:number :&callId];
}


- (BOOL)answerCall:(int)_callId {
	return [sip answerCall:_callId];
}

- (BOOL)dropCall:(int)_callId {
	return [sip hangup:_callId];
}

- (BOOL)declineCall:(int)_callId {
    return [sip declineCall:_callId];
}

- (BOOL)playDTMF:(NSNumber *)_callId :(NSString *)dtmf {
	pj_str_t _dtmf = pj_str((char *)[dtmf UTF8String]);
	return [sip playDTMF:_callId :&_dtmf];
}

- (BOOL)setMute:(BOOL)_enable {
	return [sip setMute:_enable];
}

- (BOOL)setHold:(BOOL)_enable :(int)_callId {
	return [sip setHoldEnabled:_enable :_callId];
}

- (BOOL)setSpeakerPhoneEnabled:(BOOL)_enable {
	return [sip setSpeakerPhoneEnabled:_enable];
}

- (void)showRegistrationStatus {
	[sip showRegistrationStatus];
}

- (int)getSipStatus {
	return [sip getSipStatus];
}

- (void)dealloc {
	[sip release];
	[super dealloc];
}

#pragma mark -
#pragma mark PJ Callbacks

- (void) on_registration_state:(NSNotification *)note {
	NSDictionary *dic = (NSDictionary *)[note userInfo];
	SipAccountInfo *accountInfo = (SipAccountInfo *)[dic objectForKey:DIC_ACCOUNTINFO];
	
	NSLog(@"Registration State: %@", accountInfo.statusText);
	switch ([accountInfo.status intValue]) 
	{
		case 200:
			//[self postDelegateMethod:@selector(managerConnectedWithStatusMessage:) withObject:accountInfo.statusText];
			NSLog(@"Registered");
            [self performSelectorInBackground:@selector(playSilence) withObject:nil];
            //[self playSilence];
			break;
		case 404:
		case 403:
		case 408:
			// removing account to disable further sip communications
			[sip removeAccount];
			NSLog(@"408 NOT CONNECTED");
			break;
		default:
			break;
	}
	[[NSNotificationCenter defaultCenter] postNotificationName:UIREGISTRATION_CALLBACK object:[note object] userInfo:[note userInfo]];
}

- (void) on_call_state:(NSNotification *)note {
	NSDictionary *dic = (NSDictionary *)[note userInfo];
	SipCallInfo *callInfo = (SipCallInfo *)[dic objectForKey:DIC_CALLINFO];
	//NSLog(@"State: %d, CALLER ID: %@", [callInfo.state intValue], callInfo.remoteContact);
	switch(callInfo.state)
	{
		case PJSIP_INV_STATE_NULL: // Before INVITE is sent or received.
			return;
		case PJSIP_INV_STATE_CALLING: // After INVITE is sent.
#ifdef __IPHONE_3_0
			[UIDevice currentDevice].proximityMonitoringEnabled = YES;
#else
			self.proximitySensingEnabled = YES;
#endif
			[[NSNotificationCenter defaultCenter] postNotificationName:UICALLSTATE_CALLBACK object:[note object] userInfo:[note userInfo]];
			break;
		case PJSIP_INV_STATE_INCOMING: // After INVITE is received.
			[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
			[[NSNotificationCenter defaultCenter] postNotificationName:UICALLSTATE_CALLBACK object:[note object] userInfo:[note userInfo]];
			break;
		case PJSIP_INV_STATE_EARLY: // After response with To tag.
			[[NSNotificationCenter defaultCenter] postNotificationName:UICALLSTATE_CALLBACK object:[note object] userInfo:[note userInfo]];
			break;
		case PJSIP_INV_STATE_CONNECTING: // After 2xx is sent/received.
            [self stopSilence];
			break;
		case PJSIP_INV_STATE_CONFIRMED: // After ACK is sent/received.
#ifdef __IPHONE_3_0
			[UIDevice currentDevice].proximityMonitoringEnabled = YES;
#else
			self.proximitySensingEnabled = YES;
#endif
			[[NSNotificationCenter defaultCenter] postNotificationName:UICALLSTATE_CALLBACK object:[note object] userInfo:[note userInfo]];
			break;
		case PJSIP_INV_STATE_DISCONNECTED:
			[[UIApplication sharedApplication] setIdleTimerDisabled:NO];
#ifdef __IPHONE_3_0
			[UIDevice currentDevice].proximityMonitoringEnabled = NO;
#else
			self.proximitySensingEnabled = NO;
#endif
			[[NSNotificationCenter defaultCenter] postNotificationName:UICALLSTATE_CALLBACK object:[note object] userInfo:[note userInfo]];
            //[self playSilence];
            [self performSelectorInBackground:@selector(playSilence) withObject:nil];
			break;
	}
}

- (app_config_struct *) getConfiguration {
	return &app_config;
}

#pragma mark -
#pragma mark Private
- (void)initSilence {
//    NSString *soundFile =[NSString stringWithFormat:@"%@/%@", [[NSBundle mainBundle] resourcePath], @"silence.caf"];
//    NSData *data = [NSData dataWithContentsOfFile:soundFile];
//    
//    if (data){
//        NSError *outError;
//        m_silentPlayer = [[AVAudioPlayer alloc] initWithData:data error:&outError];
//        m_silentPlayer.volume = 0.0;
//    }else{
//        NSLog(@"Unable to play silence");
//    }
}

- (void)playSilence {
//    NSLog(@"Playing silence");
//    [m_silentPlayer play];
//    m_silentPlayer.delegate = self;
}

- (Float32)audioVolume
{
    Float32 state;
    UInt32 propertySize = sizeof(CFStringRef);
    OSStatus n = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareOutputVolume, &propertySize, &state);
    if(n)
    {
        // TODO: Throw an exception
        //NSLog( @"AudioSessionGetProperty: %@", n);
    }
    return state;
}

- (void)stopSilence {
//    NSLog(@"Stopping silence");
//    m_silentPlayer.delegate = nil;
//    [m_silentPlayer stop];
}

#pragma mark -
#pragma mark Audio player callbacks

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
    // When the sound stops, wait 1 second and play it again - forever!
    //[NSThread sleepForTimeInterval:1.0f];
    [player play];
}

@end